package com.mfp.java.testYou.core.servlets;

import java.sql.SQLException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.mfp.java.testYou.core.AppContext;
import com.mfp.java.testYou.core.Constants;
import com.mfp.java.testYou.core.utils.UrlUtils;
import com.mfp.java.testYou.db.model.User;
import com.mfp.java.testYou.db.model.UserRole;
import com.mfp.java.testYou.ui.mvc.ResultsPage;
import com.mfp.java.testYou.ui.mvc.UserPage;
import com.mfp.java.testYou.ui.mvc.UsersPage;

public class ManageUserServlet extends HttpServlet {

	private static final Logger log = Logger.getLogger(ManageUserServlet.class);
	private static final long serialVersionUID = 4658721000538692199L;

	// same value as in web.xml
	public static final String URL = "/testYou/manageUser.html";

	public static final String OPERATION = "operation";

	public static final String OPERATION_NEW = "new";
	public static final String OPERATION_EDIT = "edit";
	public static final String OPERATION_DELETE = "delete";
	public static final String OPERATION_ADD = "add";
	public static final String OPERATION_CHANGE = "change";
	public static final String OPERATION_VIEW = "view";

	public static final String INPUT_NAME = "userName";
	public static final String INPUT_PASS = "passw";
	public static final String INPUT_CONF_PASS = "confPassword";
	public static final String INPUT_DEF_LANG = "defLang";
	public static final String INPUT_ROLE = "role";

	public static final String INPUT_USERID = "userId";

	public static final String USER_ID = "userId";

	public void doGet(HttpServletRequest req, HttpServletResponse resp) {
		doPost(req, resp);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse resp) {

		if (OPERATION_NEW.equals(getOperation(req))) {
			UrlUtils.forwardToTarget(req, resp, UserPage.URL);
			return;
		}

		if (OPERATION_EDIT.equals(getOperation(req))) {
			loadUser(req, UserPage.ATTR_EDIT_USER);
			UrlUtils.forwardToTarget(req, resp, UserPage.URL);
			return;
		}

		if (OPERATION_DELETE.equals(getOperation(req))) {
			deleteUser(req);
			UrlUtils.redirectToTarget(req, resp, UsersPage.URL);
			return;

		}

		if (OPERATION_ADD.equals(getOperation(req))) {
			createUser(req, resp);
			UrlUtils.forwardToTarget(req, resp, UserPage.URL);
			return;
		}

		if (OPERATION_CHANGE.equals(getOperation(req))) {
			editUser(req);
			UrlUtils.redirectToTarget(req, resp, UsersPage.URL);
			return;
		}

		if (OPERATION_VIEW.equals(getOperation(req))) {
			UrlUtils.redirectToTarget(req, resp, ResultsPage.URL);
			return;
		}

		log.error("Unknown command: " + getOperation(req));
		UrlUtils.redirectToTarget(req, resp, "/");
	}

	private String getOperation(HttpServletRequest request) {
		return request.getParameter(OPERATION);
	}

	/**
	 * Will load the user from the DB by the userID request parameter, and set
	 * the User object as request Attribute
	 * 
	 * @param request
	 * @param attrName
	 */
	private void loadUser(HttpServletRequest request, String attrName) {
		try {
			String userId = request.getParameter(INPUT_USERID);
			Integer userIdInt = new Integer(userId);
			User u = AppContext.getDAO().getUser(userIdInt);
			request.setAttribute(attrName, u);
		} catch (IllegalArgumentException e) {
			log.error("Error while loading user: " + e.getClass().getName() + " " + e.getMessage());
			AppContext.getUserSession(request).setError(Constants.I18N_ILLEGAL_ARG);
		}
	}

	private void deleteUser(HttpServletRequest req) {
		String userId = req.getParameter(USER_ID);
		try {
			Integer userIdInt = new Integer(userId);
			AppContext.getDAO().deleteUser(userIdInt);
			AppContext.getUserSession(req).setMessage(Constants.I18N_USER_DELETED);
			log.info("Deleted user with id: " + userId);
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}

	private void createUser(HttpServletRequest req, HttpServletResponse resp) {
		CharSequence pass = req.getParameter(INPUT_PASS);
		CharSequence pass2 = req.getParameter(INPUT_CONF_PASS);

		if (!pass.equals(pass2)) {
			AppContext.getUserSession(req).setError(Constants.I18N_DIFF_PASS);
			return;
		}

		try {
			User u = buildUserFromParameters(req);

			AppContext.getDAO().addUser(u, pass);
			log.info("Created user: " + u.toString());
			AppContext.getUserSession(req).setMessage(Constants.I18N_USER_CREATED);
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		} catch (IllegalArgumentException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}
	}

	private void editUser(HttpServletRequest req) {
		CharSequence pass = req.getParameter(INPUT_PASS);
		CharSequence pass2 = req.getParameter(INPUT_CONF_PASS);

		if (!pass.equals(pass2)) {
			AppContext.getUserSession(req).setError(Constants.I18N_DIFF_PASS);
			return;
		}

		if (pass == null || pass.length() == 0) {
			pass = null;
		}

		User user = buildUserFromParameters(req);

		try {
			String userId = req.getParameter(INPUT_USERID);
			Integer userIdInt = new Integer(userId);

			AppContext.getDAO().editUser(user, pass, userIdInt);
			AppContext.getUserSession(req).setMessage(Constants.I18N_USER_EDITED);
			log.info("Edited user: " + user.toString());

		} catch (IllegalArgumentException e) {
			log.error(e.getClass().getName() + " " + e.getMessage());
			AppContext.getUserSession(req).setError(Constants.I18N_ILLEGAL_ARG);
		} catch (SQLException e) {
			AppContext.getUserSession(req).setError(Constants.I18N_DB_ERROR);
			log.error(e.getClass().getName() + " " + e.getMessage());
		}

	}

	private User buildUserFromParameters(HttpServletRequest req) throws IllegalArgumentException {
		User u = new User();
		u.setLang(req.getParameter(INPUT_DEF_LANG));
		u.setUserName(req.getParameter(INPUT_NAME));
		try {
			String roleName = req.getParameter(INPUT_ROLE);
			u.setRole(UserRole.valueOf(roleName));
		} catch (NullPointerException e) {
			log.warn(e.getClass().getName() + " " + e.getMessage());
			throw new IllegalArgumentException(e);
		}
		return u;
	}
}
